import Vue, {
  computed,
  defineComponent,
  getCurrentInstance,
  provide,
  Ref,
  watch,
  h,
  reactive,
} from 'vue'
import {
  createSchemaField,
  RecursionField,
  useField,
  useFieldSchema,
  useForm,
  Field,
  Schema,
} from '@formily/vue'
import {
  createForm,
  Form,
  FormPath,
  ObjectField,
  onFieldMount,
  onFieldReact,
  onFormInit,
  onFormMount,
} from '@formily/core'
import { ISchema } from '@formily/json-schema'
import { inject, ref, shallowRef } from 'vue'
import { RouteParams, useRoute, useRouter } from 'vue-router'
import { composeExport } from '@formily/vxe-table/src/__builtins__'
import {
  useTableInstance,
  VXETablePropsSymbol,
  ArrayTable,
} from '@formily/vxe-table/src/array-table'
import {
  Table,
  Column,
  Colgroup,
  Pager,
  Select,
  Option,
  Optgroup,
  Grid,
  Button,
  VxeTableProps,
  VxeGridEventProps,
  Switch,
} from 'vxe-table'
import {
  useBFGridDomain,
  useBFGridServices,
  useBFGridDialog,
} from './domain-base'
import { ArrayBase, FormDialog, FormLayout } from '@formily/vxe-table/src'
import { SlickList, SlickItem, HandleDirective } from 'vue-slicksort'
import * as Components from '@formily/vxe-table/src'

const { SchemaField } = createSchemaField({
  components: {
    ...Components,
  },
  scope: {
    // global scope 全局的 scope
    BFPermission: (...args) => {
      console.log('validate permission', args)
      return false
    },
  },
})

const ToolbarInner = (props, context) => context.slots?.default?.()

const Link = defineComponent({
  props: {
    name: String,
    type: String,
    label: String,
    linkTo: String, // 需要打开的view的path
  },
  setup(props, { attrs, slots }) {
    const prefixRef = inject('prefix', ref('bf'))
    const route = useRoute()
    const router = useRouter()
    const dialogMethodRef = useBFGridDialog()

    // TODO::根据不同type渲染不同的组件？ 要不就干脆套娃内部组件只显示外面控制事件
    return () => {
      const className = prefixRef.value + '__action'
      // router.push(props.linkTo)
      return (
        <span class={className} onClick={() => dialogMethodRef.value(props)}>
          {slots.default ? (
            slots.default()
          ) : (
            <Button {...attrs}>{props.label}</Button>
          )}
        </span>
      )
    }
  },
})

const Action = defineComponent({
  props: {
    name: String, // 对应service的名称
    type: String,
    label: String,
    service: String, // 对应的service
  },
  inheritAttrs: false,
  setup(props, { attrs, slots }) {
    const prefixRef = inject('prefix', ref('bf'))
    // 获取对应到的 service
    const servicesRef = useBFGridServices()
    const serviceRef = computed(() => {
      return servicesRef.value.find((service) => service.name == props.service)
    })
    // 获取 model
    const modelRef = useBFGridDomain()
    const fieldRef = useField()
    const fieldSchemaRef = useFieldSchema()
    const route = useRoute()
    return () => {
      const className = prefixRef.value + '__action'
      const actionName = props.name
      const service = serviceRef.value
      const params = route.query
      const model = modelRef.value
      // TODO::model实例还没有获取到
      return (
        <span
          class={className}
          onClick={() => {
            service?.resolver(params, model, props)
          }}
        >
          {slots.default ? (
            slots.default()
          ) : (
            <Button {...attrs}>{props.label}</Button>
          )}
        </span>
      )
    }
  },
})

const Refresh = defineComponent({
  props: ['value', 'onChnage'],
  setup(props, { attrs, slots }) {
    const prefixRef = inject('prefix', ref('bf'))
    const modelRef = useBFGridDomain()
    return () => {
      const className = prefixRef.value + '__action'

      return (
        <span
          class={className}
          onClick={() => {
            modelRef.value?.refresh()
          }}
        >
          {slots.default ? slots.default() : <Button {...attrs}>刷新</Button>}
        </span>
      )
    }
  },
})

const ArrayBaseSortHandle = defineComponent({
  props: ['index'],
  directives: {
    handle: HandleDirective,
  },
  setup(props, { attrs }) {
    return () => {
      return <i class="vxe-icon--menu" vHandle />
    }
  },
})
const Custom = defineComponent({
  props: ['value', 'onChnage', 'disabledColumns'],
  setup(props, { attrs, slots }) {
    const prefixRef = inject('prefix', ref('bf'))
    const modelRef = useBFGridDomain()
    const fieldSchemaRef = useFieldSchema()
    return () => {
      const disables = props.disabledColumns
      const schema = fieldSchemaRef.value
      const className = prefixRef.value + '__action'

      const tableSchema = schema.root.properties.gridapp.reduceProperties(
        (buffer, schema) => {
          if (schema['x-component'] == 'BFGridApp.Table') {
            return schema
          }
        },
        {}
      )

      // TODO::只考虑了但对象的模式的schema，没有考虑多个对象的schema。Schema.items 可以是一个数组的
      // TODO::visible 是否结合field属性进行联合判断
      function buildTree(schema: Schema, depth = 0) {
        if (!schema) return []
        return schema.reduceProperties((acc, schema, name, index) => {
          if (!schema['x-component']?.includes('Table')) return acc
          schema['x-index'] = index
          const label = schema.title ?? name
          acc.push({
            address: schema,
            disabled: disables.includes(label),
            index,
            label,
            visible: schema['x-visible'] ?? true,
            schema,
            children: [...buildTree(schema)],
          })
          return acc
        }, [] as any)
      }

      function buildSortTree(treeNodes: Ref<any[]>, depth = 0) {
        return (
          <SlickList
            v-model:list={treeNodes.value}
            useDragHandle={true}
            axis={'y'}
            style={{ marginLeft: depth * 8 + 'px' }}
          >
            {treeNodes.value.map((e, index) => {
              const computedValue = computed({
                get() {
                  return e.children
                },
                set(value) {
                  e.children = value
                },
              })
              return (
                <SlickItem index={index}>
                  <ArrayBaseSortHandle index={index}></ArrayBaseSortHandle>
                  {`${e.label || '----'}`}
                  <Switch v-model={e.visible}></Switch>
                  {e.children.length > 0 &&
                    buildSortTree(computedValue as Ref, depth + 1)}
                </SlickItem>
              )
            })}
          </SlickList>
        )
      }

      return (
        <span
          class={className}
          onClick={() => {
            const treeData = ref(buildTree(tableSchema.items as Schema))
            FormDialog(
              { title: '显示列', showZoom: true, resize: true },
              () => <div id="id">{buildSortTree(treeData)}</div>
            )
              .forConfirm((payload, next) => {
                function syncIndex(data) {
                  data.forEach((data, index) => {
                    data.schema['x-index'] = index
                    data.schema['x-visible'] = data.visible
                    if (data.children.length > 0) {
                      syncIndex(data.children)
                    }
                  })
                }
                syncIndex(treeData.value)
                modelRef.value.patchSchema(tableSchema.root)
                next()
              })
              .open()
          }}
        >
          {slots.default ? slots.default() : <Button {...attrs}>显示列</Button>}
        </span>
      )
    }
  },
})

export const Toolbar = composeExport(ToolbarInner, {
  Link: Link,
  Action: Action,
  Refresh,
  Custom,
})
